<?php

namespace SinoPHP\BbdBoss\Library;

use LinkORB\Component\Etcd\Exception\KeyNotFoundException;
use LinkORB\Component\Etcd\Client as EtcdClient;

class Etcd {

    /**
     * Cache层级
     */
    const LAYER_LEVEL_SOURCE = 0; // 回源层

    const LAYER_LEVEL_EDGE = 1; // 边缘层

    const LAYER_LEVEL_PARENT = 2; // 父层

    const LAYER_LEVEL_SUPER = 3; // 超父层

    const LAYER_LEVEL_DYNAMICS = 4; // 动态层

    /**
     * ETCD客户端链接
     *
     * @var EtcdClient
     */
    protected $etcdClient;

    /**
     * 前缀(用于区分环境)
     *
     * @var string
     */
    protected $prefix;

    /**
     * ETCD客户端实例
     *
     * @var Etcd
     */
    protected static $instance;

    protected function __construct() {
        $this->etcdClient = new EtcdClient(config('host', 'etcd'));
        $this->prefix = trim(config('prefix', 'etcd'), '/');
    }

    /**
     * 获取ETCD客户端实例
     *
     * @return Etcd
     */
    public static function instance() {
        if (!(self::$instance instanceof EtcdClient)) {
            self::$instance = new self();
        }

        return self::$instance;
    }

    /**
     * 获取ETCD客户端
     *
     * @return EtcdClient
     */
    public function etcdClient() {
        return $this->etcdClient;
    }

    /**
     * 查询域名在某一层级下的所有记录
     *
     * @param  string  $domain
     * @param  integer $level
     * @return array
     */
    public function listDomainRecordsByLevel($domain, $level) {
        $keyPrefix = $this->getSkyDnsURLByLevel($level);
        $domain = str_replace('*', '', $domain);
        $list = explode('.', $domain);
        krsort($list);
        $keyMiddle = implode('/', $list);
        $listKey = $keyPrefix . $keyMiddle;

        $data = $this->etcdClient->listDir($listKey, true);
        if (empty($data['node']['nodes'])) {
            return array();
        }

        $recordList = array();
        foreach ($data['node']['nodes'] as $row) {
            $exp = explode('/', $row['key']);
            $line = array_pop($exp);
            $recordList[$line] = json_decode($row['value'], true);
        }

        return $recordList;
    }

    /**
     * 获取ETCD数据
     *
     * @param  $domain
     * @param  $level
     * @param  $line
     * @return string
     */
    public function getDataFromEtcd($domain, $level, $line) {
        $key = $this->getKey($domain, $level, $line);

        try {
            return $this->etcdClient->get($key);
        } catch (KeyNotFoundException $e) {
            return false;
        }
    }

    /**
     * 删除ETCD数据
     *
     * @param  $domain
     * @param  $level
     * @param  $line
     * @return array|\stdClass
     * @throws \LinkORB\Component\Etcd\Exception\EtcdException
     */
    public function removeDataFromEtcd($domain, $level, $line) {
        $key = $this->getKey($domain, $level, $line);

        return $this->etcdClient->rm($key);
    }

    /**
     * 设置ETCD数据
     *
     * 不存在, 则创建; 已存在, 则修改
     *
     * @param  string  $domain
     * @param  integer $level
     * @param  string  $line
     * @param  array   $data
     * @return \stdClass
     */
    public function setDataToEtcd($domain, $level, $line, array $data) {
        $key = $this->getKey($domain, $level, $line);

        return $this->etcdClient->set($key, json_encode($data));
    }

    /**
     * 组装Key
     *
     * @param  string  $domain
     * @param  integer $level
     * @param  string  $line
     * @return string
     */
    protected function getKey($domain, $level, $line) {
        $keyPrefix = $this->getSkyDnsURLByLevel($level);
        $domain = str_replace('*', '', $domain);
        $list = explode('.', $domain);
        krsort($list);
        $keyMiddle = implode('/', $list);
        $keySuffix = $this->getLineString($line);
        $key = $keyPrefix . $keyMiddle . '/' . $keySuffix;

        return $key;
    }

    /**
     * 获取线路标识
     *
     * @param  string $line
     * @return string
     */
    public function getLineString($line) {
        $domainStr = 'default';
        switch ($line) {
            case '联通':
                $domainStr = 'cnc';
                break;
            case '电信':
                $domainStr = 'ctl';
                break;
            case '移动':
                $domainStr = 'cmb';
                break;
            case '铁通':
                $domainStr = 'crc';
                break;
            case '教育网':
                $domainStr = 'cer';
                break;
            case '电信通':
                $domainStr = 'gwn';
                break;
            case '其他':
                $domainStr = 'oth';
                break;
        }

        return $domainStr;
    }

    /**
     * 根据Cache层级获取SkyDNS URL
     *
     * @param  integer $level
     * @return string
     */
    public function getSkyDnsUrlByLevel($level = self::LAYER_LEVEL_EDGE) {
        switch ($level) {
            case self::LAYER_LEVEL_EDGE:
                $skyDnsUrl = '/' . $this->prefix . '_elc/';
                break;
            case self::LAYER_LEVEL_PARENT:
                $skyDnsUrl = '/' . $this->prefix . '_plc/';
                break;
            case self::LAYER_LEVEL_SUPER:
                $skyDnsUrl = '/' . $this->prefix . '_slc/';
                break;
            case self::LAYER_LEVEL_DYNAMICS:
                $skyDnsUrl = '/' . $this->prefix . '_dlc/';
                break;
            default:
                $skyDnsUrl = '/' . $this->prefix . '_elc/';
        }

        return $skyDnsUrl;
    }

}